from rest_framework import serializers
from goods.models import SKU
from .models import OrderInfo,OrderGoods
from django.utils import timezone
from decimal import Decimal
from django_redis import get_redis_connection
from django.db import transaction

"""
freight	decimal	是	运费
skus	sku[]	是	结算的商品列表

id	int	是	商品id
name	str	是	商品名称
default_image_url	str	是	商品默认图片
price	decimal	是	商品单价
count	int	是	商品数量
"""
class OrderCartSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(label="商品数量")
    class Meta:
        model = SKU
        fields = ("id","name","default_image_url","price","count")

class OrderSettlementSerializer(serializers.Serializer):
    freight = serializers.DecimalField(label="运费",max_digits=10,decimal_places=2)
    skus = OrderCartSerializer(many=True)

#保存订单序列化器
"""
参数	类型	是否必须	说明
address	int	是	收货地址id
pay_method	int	是	支付方式
返回数据

参数	类型	是否必须	说明
order_id	char	是	订单编号
"""
class OrderCommitSerializer(serializers.ModelSerializer):

    class Meta:
        model = OrderInfo
        fields = ("order_id","address","pay_method")

        read_only_fields = ("order_id",)

        extra_kwargs = {
            "address":{
                "required":True,
                "write_only":True
            },
            "pay_method":{
                "required":True,
                "write_only":True
            },
        }

    #重写的目的,创建order,OrderGoods数据,保存单数据库
    def create(self, validated_data):
        #1,获取用户对象
        user = self.context["request"].user

        #2,获取地址,支付方式,设置订单状态
        address = validated_data["address"]
        pay_method = validated_data["pay_method"]
        if pay_method == OrderInfo.PAY_METHODS_ENUM["CASH"]:
            status = OrderInfo.ORDER_STATUS_ENUM["UNSEND"]
        else:
            status = OrderInfo.ORDER_STATUS_ENUM["UNPAID"]

        #3,创建order_id
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + ("%06d"%user.id)

        #3,1 开启事物
        with transaction.atomic():
            #设置一个事物开启的标记点,用来,提交,或者回滚的
            save_point = transaction.savepoint()

            #4,创建订单对象
            order = OrderInfo.objects.create(
                order_id = order_id,
                user=user,
                address=address,
                total_count=0,
                total_amount=Decimal("0.0"),
                freight=Decimal("10"),
                pay_method=pay_method,
                status=status
            )

            #5,获取redis的商品数据
            redis_conn = get_redis_connection("cart")
            redis_cart = redis_conn.hgetall("cart_%s"%user.id)
            redis_cart_selected = redis_conn.smembers("cart_selected_%s"%user.id)

            #6,遍历需要结算的商品
            for sku_id in redis_cart_selected:
                #6,1 获取sku对象
                sku = SKU.objects.get(id=sku_id)

                #6,2 结算获取商品数量
                count =  int(redis_cart[sku_id])

                #6,3判断库存是否充足
                if count > sku.stock:

                    #回滚
                    transaction.savepoint_rollback(save_point)

                    raise serializers.ValidationError("库存不足")

                #模拟并发过程
                # import time
                # time.sleep(10)

                #6,4库存减少,销量增加
                # sku.stock -= count
                # sku.sales += count
                # sku.save()

                #先查询原始的库存
                old_stock = sku.stock
                old_sales = sku.sales

                #组织新数据
                new_stock = old_stock - count
                new_sales = old_sales + count

                #修改数据库, ret表示影响的行数,如果0,表示修改失败了
                ret =  SKU.objects.filter(id=sku_id,stock=old_stock,sales=old_sales).update(stock=new_stock,sales=new_sales)

                if ret == 0:
                    #
                    # transaction.savepoint_rollback(save_point)
                    #
                    # raise serializers.ValidationError("下单失败")

                    continue

                #6,5创建orderGoods对象
                OrderGoods.objects.create(
                    order=order,
                    sku=sku,
                    count=count,
                    price=sku.price
                )

                #6,6 设置order中的订单数量和总价格
                order.total_count += count
                order.total_amount += (sku.price * count)

            #7,保存订单
            order.save()

        #提交事物
        transaction.savepoint_commit(save_point)


        #8,清除已经生成订单的商品
        redis_conn.hdel("cart_%s"%user.id,*redis_cart_selected)
        redis_conn.srem("cart_selected_%s"%user.id,*redis_cart_selected)

        #9,返回订单
        return order